from fastapi import FastAPI, Request, HTTPException, Depends
from fastapi.param_functions import Depends
from fastapi.security.oauth2 import OAuth2PasswordBearer
from starlette.requests import Request
from tortoise.contrib.fastapi import register_tortoise
from fastapi.security import OAuth2AuthorizationCodeBearer, OAuth2PasswordRequestForm

from tortoise.signals import post_save
from typing import List, Optional, Type
from tortoise import BaseDBAsyncClient

from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates

import send_email
from models import *
from authentication import *

app = FastAPI()
templates = Jinja2Templates(directory='templates')
oath2_scheme = OAuth2PasswordBearer(tokenUrl='token')


@app.post('/token')
async def generate_token(request_form: OAuth2PasswordRequestForm = Depends()):
    token = await token_generator(request_form.username, request_form.password)
    return {'access_token': token, 'token_type': 'Bearer'}


# @app.get('/user_detail', response_model=user_pydanticOut)
@app.get('/user_detail')
async def get_current_user(token: str = Depends(oath2_scheme)):
    user_info = jwt.decode(token, config_credentials['TOKEN_SECRET'], algorithms=['HS256'])
    user = User.get(id=user_info['id'])
    # user = User.get(username=user_info['username'])
    return await user_pydanticOut.from_queryset_single(user)


@post_save(User)
async def create_business(
    sender: "Type[User]",
    instance: User,
    created: bool,
    using_db: "Optional[BaseDBAsyncClient]",
    update_fields: List[str],
) -> None:
    if created:
        business_obj = await Business.create(
            business_name=instance.username,
            owner=instance,
        )
        await business_pydantic.from_tortoise_orm(business_obj)
        # await send_email([instance.email], instance)
        await send_email.send_email([instance.email], instance)
        # await send_email.send_email('docker fastapi')


@app.get('/', tags=['home_page', ])
async def home():
    return {'hi': 'fastPAI'}


@app.get('/business/{id}', response_model=business_pydantic)
async def business_detail(id: int):
    try:
        business_obj = await Business.get(id=id)
    except:
        return {'error': 'no object found!'}
    return business_pydantic.from_tortoise_orm(business_obj)


@app.get('/verification', response_class=HTMLResponse)
async def email_verification(request: Request, token: str):
    user = await very_token(token)
    if user and not user.is_verified:
        user.is_verified = True
        await user.save()
        return templates.TemplateResponse('user_verify_success.html', {'request': request, 'username': user.username})
    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail='Invalid token or expired token',
        headers={"WWW-Authenticat": "Bearer"}
    )


@app.post('/register', response_model=user_pydanticOut)
async def user_register(user: user_pydanticIn):
    user_info = user.dict(exclude_unset=True)
    user_info["password"] = get_hashed_password(user_info['password'])
    user_obj = await User.create(**user_info)
    return await user_pydanticOut.from_tortoise_orm(user_obj)
    # return {
    #     'status': 'ok',
    #     'data': {f"hellow {new_user.username}, thanks for choosing our service. Please check your email inbox and click on the link to conform yoour registration."}
    # }

register_tortoise(
    app,
    db_url='sqlite://t1.sqlite3',
    modules={'models': ['models']},
    generate_schemas=True,
    add_exception_handlers=True
)

# if __name__ == "__main__":
#     import uvicorn
#     uvicorn.run(app, host="0.0.0.0", port=8081)
